/*
 * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// DO NO EDIT! - This file was generated by JavaScriptCore/wasm/generateWasmOpsHeader.py

#pragma once

#if ENABLE(WEBASSEMBLY)

#include <cstdint>

namespace JSC { namespace Wasm {

static constexpr unsigned expectedVersionNumber = 1;

static constexpr unsigned numTypes = 8;

#define FOR_EACH_WASM_TYPE(macro) \
    macro(I32, -0x1, B3::Int32, 0) \
    macro(Void, -0x40, B3::Void, 1) \
    macro(I64, -0x2, B3::Int64, 2) \
    macro(F32, -0x3, B3::Float, 3) \
    macro(Func, -0x20, B3::Void, 4) \
    macro(Anyref, -0x11, B3::Int64, 5) \
    macro(Funcref, -0x10, B3::Int64, 6) \
    macro(F64, -0x4, B3::Double, 7)
#define CREATE_ENUM_VALUE(name, id, b3type, inc) name = id,
enum Type : int8_t {
    FOR_EACH_WASM_TYPE(CREATE_ENUM_VALUE)
};
#undef CREATE_ENUM_VALUE

#define CREATE_CASE(name, id, b3type, inc) case id: return true;
template <typename Int>
inline bool isValidType(Int i)
{
    switch (i) {
    default: return false;
    FOR_EACH_WASM_TYPE(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return false;
}
#undef CREATE_CASE

#define CREATE_CASE(name, id, b3type, inc) case name: return b3type;
inline B3::Type toB3Type(Type type)
{
    switch (type) {
    FOR_EACH_WASM_TYPE(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return B3::Void;
}
#undef CREATE_CASE

#define CREATE_CASE(name, id, b3type, inc) case name: return #name;
inline const char* makeString(Type type)
{
    switch (type) {
    FOR_EACH_WASM_TYPE(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return nullptr;
}
#undef CREATE_CASE

#define CREATE_CASE(name, id, b3type, inc) case id: return inc;
inline int linearizeType(Type type)
{
    switch (type) {
    FOR_EACH_WASM_TYPE(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return 0;
}
#undef CREATE_CASE

#define CREATE_CASE(name, id, b3type, inc) case inc: return name;
inline Type linearizedToType(int i)
{
    switch (i) {
    FOR_EACH_WASM_TYPE(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return Void;
}
#undef CREATE_CASE


#define FOR_EACH_WASM_SPECIAL_OP(macro) \
    macro(F64Const, 0x44, Oops, 0) \
    macro(RefNull, 0xd0, Oops, 1) \
    macro(RefFunc, 0xd2, Oops, 2) \
    macro(GrowMemory, 0x40, Oops, 3) \
    macro(I64Const, 0x42, Oops, 4) \
    macro(TeeLocal, 0x22, Oops, 5) \
    macro(SetLocal, 0x21, Oops, 6) \
    macro(I32Const, 0x41, Oops, 7) \
    macro(CurrentMemory, 0x3f, Oops, 8) \
    macro(F32Const, 0x43, Oops, 9) \
    macro(SetGlobal, 0x24, Oops, 10) \
    macro(GetGlobal, 0x23, Oops, 11) \
    macro(Call, 0x10, Oops, 12) \
    macro(TableSet, 0x26, Oops, 13) \
    macro(TableGet, 0x25, Oops, 14) \
    macro(RefIsNull, 0xd1, Oops, 15) \
    macro(GetLocal, 0x20, Oops, 16) \
    macro(CallIndirect, 0x11, Oops, 17)

#define FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \
    macro(Return, 0xf, Oops, 0) \
    macro(Nop, 0x1, Oops, 1) \
    macro(Drop, 0x1a, Oops, 2) \
    macro(BrIf, 0xd, Oops, 3) \
    macro(Br, 0xc, Oops, 4) \
    macro(Select, 0x1b, Oops, 5) \
    macro(Unreachable, 0x0, Oops, 6) \
    macro(Else, 0x5, Oops, 7) \
    macro(BrTable, 0xe, Oops, 8) \
    macro(Loop, 0x3, Oops, 9) \
    macro(If, 0x4, Oops, 10) \
    macro(End, 0xb, Oops, 11) \
    macro(Block, 0x2, Oops, 12)

#define FOR_EACH_WASM_SIMPLE_UNARY_OP(macro) \
    macro(F32Ceil, 0x8d, Ceil, 0) \
    macro(F32DemoteF64, 0xb6, DoubleToFloat, 1) \
    macro(I32Clz, 0x67, Clz, 2) \
    macro(F64ConvertUI32, 0xb8, IToD(ZExt32(@0)), 3) \
    macro(F32ReinterpretI32, 0xbe, BitwiseCast, 4) \
    macro(F32Sqrt, 0x91, Sqrt, 5) \
    macro(I64Eqz, 0x50, Equal(i64(0), @0), 6) \
    macro(I64Clz, 0x79, Clz, 7) \
    macro(F32Neg, 0x8c, Neg, 8) \
    macro(F64Abs, 0x99, Abs, 9) \
    macro(F32ConvertSI64, 0xb4, IToF, 10) \
    macro(F64ConvertSI32, 0xb7, IToD, 11) \
    macro(F32ConvertUI32, 0xb3, IToF(ZExt32(@0)), 12) \
    macro(F64Ceil, 0x9b, Ceil, 13) \
    macro(F64Floor, 0x9c, Floor, 14) \
    macro(F32Abs, 0x8b, Abs, 15) \
    macro(I32ReinterpretF32, 0xbc, BitwiseCast, 16) \
    macro(F64ConvertSI64, 0xb9, IToD, 17) \
    macro(F64PromoteF32, 0xbb, FloatToDouble, 18) \
    macro(I64ExtendUI32, 0xad, ZExt32, 19) \
    macro(F64ReinterpretI64, 0xbf, BitwiseCast, 20) \
    macro(F32Floor, 0x8e, Floor, 21) \
    macro(F32ConvertSI32, 0xb2, IToF, 22) \
    macro(I32Eqz, 0x45, Equal(i32(0), @0), 23) \
    macro(I64ReinterpretF64, 0xbd, BitwiseCast, 24) \
    macro(F64Sqrt, 0x9f, Sqrt, 25) \
    macro(I32WrapI64, 0xa7, Trunc, 26) \
    macro(I64ExtendSI32, 0xac, SExt32, 27) \
    macro(F64Neg, 0x9a, Neg, 28)

#define FOR_EACH_WASM_UNARY_OP(macro) \
    FOR_EACH_WASM_SIMPLE_UNARY_OP(macro) \
    macro(I64TruncSF32, 0xae, Oops, 0) \
    macro(F32ConvertUI64, 0xb5, Oops, 1) \
    macro(I32Ctz, 0x68, Oops, 2) \
    macro(I32TruncSF64, 0xaa, Oops, 3) \
    macro(I32TruncUF64, 0xab, Oops, 4) \
    macro(I32Popcnt, 0x69, Oops, 5) \
    macro(I64Popcnt, 0x7b, Oops, 6) \
    macro(I64Ctz, 0x7a, Oops, 7) \
    macro(I32TruncSF32, 0xa8, Oops, 8) \
    macro(I64TruncUF64, 0xb1, Oops, 9) \
    macro(I64TruncSF64, 0xb0, Oops, 10) \
    macro(F64ConvertUI64, 0xba, Oops, 11) \
    macro(F64Nearest, 0x9e, Oops, 12) \
    macro(F64Trunc, 0x9d, Oops, 13) \
    macro(F32Trunc, 0x8f, Oops, 14) \
    macro(I32TruncUF32, 0xa9, Oops, 15) \
    macro(I64TruncUF32, 0xaf, Oops, 16) \
    macro(F32Nearest, 0x90, Oops, 17)

#define FOR_EACH_WASM_SIMPLE_BINARY_OP(macro) \
    macro(I64ShrS, 0x87, SShr(@0, Trunc(@1)), 0) \
    macro(I32Mul, 0x6c, Mul, 1) \
    macro(I32Sub, 0x6b, Sub, 2) \
    macro(F64Le, 0x65, LessEqual, 3) \
    macro(F64Ne, 0x62, NotEqual, 4) \
    macro(F64Lt, 0x63, LessThan, 5) \
    macro(F32Max, 0x97, Select(Equal(@0, @1), BitAnd(@0, @1), Select(LessThan(@0, @1), @1, Select(GreaterThan(@0, @1), @0, Add(@0, @1)))), 6) \
    macro(F64Mul, 0xa2, Mul, 7) \
    macro(F32Div, 0x95, Div, 8) \
    macro(F32Copysign, 0x98, BitwiseCast(BitOr(BitAnd(BitwiseCast(@1), i32(0x80000000)), BitAnd(BitwiseCast(@0), i32(0x7fffffff)))), 9) \
    macro(I64And, 0x83, BitAnd, 10) \
    macro(F32Ne, 0x5c, NotEqual, 11) \
    macro(F64Gt, 0x64, GreaterThan, 12) \
    macro(F64Ge, 0x66, GreaterEqual, 13) \
    macro(I64GtS, 0x55, GreaterThan, 14) \
    macro(I64GtU, 0x56, Above, 15) \
    macro(F64Div, 0xa3, Div, 16) \
    macro(F32Add, 0x92, Add, 17) \
    macro(I64Or, 0x84, BitOr, 18) \
    macro(I32LeU, 0x4d, BelowEqual, 19) \
    macro(I32LeS, 0x4c, LessEqual, 20) \
    macro(I64Ne, 0x52, NotEqual, 21) \
    macro(I32And, 0x71, BitAnd, 22) \
    macro(I32LtU, 0x49, Below, 23) \
    macro(I64Rotr, 0x8a, RotR(@0, Trunc(@1)), 24) \
    macro(I32LtS, 0x48, LessThan, 25) \
    macro(I32Eq, 0x46, Equal, 26) \
    macro(F64Copysign, 0xa6, BitwiseCast(BitOr(BitAnd(BitwiseCast(@1), i64(0x8000000000000000)), BitAnd(BitwiseCast(@0), i64(0x7fffffffffffffff)))), 27) \
    macro(I64Rotl, 0x89, RotL(@0, Trunc(@1)), 28) \
    macro(F32Lt, 0x5d, LessThan, 29) \
    macro(F64Eq, 0x61, Equal, 30) \
    macro(F32Le, 0x5f, LessEqual, 31) \
    macro(F32Ge, 0x60, GreaterEqual, 32) \
    macro(I32ShrU, 0x76, ZShr, 33) \
    macro(I32ShrS, 0x75, SShr, 34) \
    macro(I32GeU, 0x4f, AboveEqual, 35) \
    macro(I32GeS, 0x4e, GreaterEqual, 36) \
    macro(I32Shl, 0x74, Shl, 37) \
    macro(I32Xor, 0x73, BitXor, 38) \
    macro(F64Min, 0xa4, Select(Equal(@0, @1), BitOr(@0, @1), Select(LessThan(@0, @1), @0, Select(GreaterThan(@0, @1), @1, Add(@0, @1)))), 39) \
    macro(F32Mul, 0x94, Mul, 40) \
    macro(I64Sub, 0x7d, Sub, 41) \
    macro(I32Add, 0x6a, Add, 42) \
    macro(F64Sub, 0xa1, Sub, 43) \
    macro(I32Or, 0x72, BitOr, 44) \
    macro(I64LtU, 0x54, Below, 45) \
    macro(I64LtS, 0x53, LessThan, 46) \
    macro(I64Xor, 0x85, BitXor, 47) \
    macro(I64GeU, 0x5a, AboveEqual, 48) \
    macro(F32Min, 0x96, Select(Equal(@0, @1), BitOr(@0, @1), Select(LessThan(@0, @1), @0, Select(GreaterThan(@0, @1), @1, Add(@0, @1)))), 49) \
    macro(I64Mul, 0x7e, Mul, 50) \
    macro(F32Sub, 0x93, Sub, 51) \
    macro(F64Add, 0xa0, Add, 52) \
    macro(I64GeS, 0x59, GreaterEqual, 53) \
    macro(I32Ne, 0x47, NotEqual, 54) \
    macro(F32Eq, 0x5b, Equal, 55) \
    macro(I64Eq, 0x51, Equal, 56) \
    macro(I64ShrU, 0x88, ZShr(@0, Trunc(@1)), 57) \
    macro(I64Shl, 0x86, Shl(@0, Trunc(@1)), 58) \
    macro(F32Gt, 0x5e, GreaterThan, 59) \
    macro(I32Rotl, 0x77, RotL, 60) \
    macro(I32Rotr, 0x78, RotR, 61) \
    macro(I32GtU, 0x4b, Above, 62) \
    macro(I32GtS, 0x4a, GreaterThan, 63) \
    macro(F64Max, 0xa5, Select(Equal(@0, @1), BitAnd(@0, @1), Select(LessThan(@0, @1), @1, Select(GreaterThan(@0, @1), @0, Add(@0, @1)))), 64) \
    macro(I64LeU, 0x58, BelowEqual, 65) \
    macro(I64LeS, 0x57, LessEqual, 66) \
    macro(I64Add, 0x7c, Add, 67)

#define FOR_EACH_WASM_BINARY_OP(macro) \
    FOR_EACH_WASM_SIMPLE_BINARY_OP(macro) \
    macro(I32DivU, 0x6e, Oops, 0) \
    macro(I32DivS, 0x6d, Oops, 1) \
    macro(I32RemU, 0x70, Oops, 2) \
    macro(I32RemS, 0x6f, Oops, 3) \
    macro(I64RemS, 0x81, Oops, 4) \
    macro(I64RemU, 0x82, Oops, 5) \
    macro(I64DivU, 0x80, Oops, 6) \
    macro(I64DivS, 0x7f, Oops, 7)

#define FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \
    macro(I64Load32U, 0x35, Oops, 0) \
    macro(I64Load32S, 0x34, Oops, 1) \
    macro(I32Load16S, 0x2e, Oops, 2) \
    macro(I32Load16U, 0x2f, Oops, 3) \
    macro(I64Load, 0x29, Oops, 4) \
    macro(F64Load, 0x2b, Oops, 5) \
    macro(I32Load8S, 0x2c, Oops, 6) \
    macro(I32Load8U, 0x2d, Oops, 7) \
    macro(I32Load, 0x28, Oops, 8) \
    macro(F32Load, 0x2a, Oops, 9) \
    macro(I64Load8U, 0x31, Oops, 10) \
    macro(I64Load8S, 0x30, Oops, 11) \
    macro(I64Load16S, 0x32, Oops, 12) \
    macro(I64Load16U, 0x33, Oops, 13)

#define FOR_EACH_WASM_MEMORY_STORE_OP(macro) \
    macro(I64Store16, 0x3d, Oops, 0) \
    macro(I64Store8, 0x3c, Oops, 1) \
    macro(I32Store, 0x36, Oops, 2) \
    macro(I32Store16, 0x3b, Oops, 3) \
    macro(F32Store, 0x38, Oops, 4) \
    macro(I64Store, 0x37, Oops, 5) \
    macro(F64Store, 0x39, Oops, 6) \
    macro(I32Store8, 0x3a, Oops, 7) \
    macro(I64Store32, 0x3e, Oops, 8)

#define FOR_EACH_WASM_EXT_TABLE_OP(macro) \
    macro(TableFill, 0x11, Oops, 0) \
    macro(TableGrow, 0x10, Oops, 1) \
    macro(TableSize, 0xf, Oops, 2)


#define FOR_EACH_WASM_OP(macro) \
    FOR_EACH_WASM_SPECIAL_OP(macro) \
    FOR_EACH_WASM_CONTROL_FLOW_OP(macro) \
    FOR_EACH_WASM_UNARY_OP(macro) \
    FOR_EACH_WASM_BINARY_OP(macro) \
    FOR_EACH_WASM_MEMORY_LOAD_OP(macro) \
    FOR_EACH_WASM_MEMORY_STORE_OP(macro) \
    macro(ExtTable, 0xFC, Oops, 0)

#define CREATE_ENUM_VALUE(name, id, b3op, inc) name = id,

enum OpType : uint8_t {
    FOR_EACH_WASM_OP(CREATE_ENUM_VALUE)
};

template<typename Int>
inline bool isValidOpType(Int i)
{
    // Bitset of valid ops.
    static const uint8_t valid[] = { 0x3f, 0xf8, 0x3, 0xc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x10 };
    return 0 <= i && i <= 252 && (valid[i / 8] & (1 << (i % 8)));
}

enum class BinaryOpType : uint8_t {
    FOR_EACH_WASM_BINARY_OP(CREATE_ENUM_VALUE)
};

enum class UnaryOpType : uint8_t {
    FOR_EACH_WASM_UNARY_OP(CREATE_ENUM_VALUE)
};

enum class LoadOpType : uint8_t {
    FOR_EACH_WASM_MEMORY_LOAD_OP(CREATE_ENUM_VALUE)
};

enum class StoreOpType : uint8_t {
    FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_ENUM_VALUE)
};

enum class ExtTableOpType : uint8_t {
    FOR_EACH_WASM_EXT_TABLE_OP(CREATE_ENUM_VALUE)
};

#undef CREATE_ENUM_VALUE

inline bool isControlOp(OpType op)
{
    switch (op) {
#define CREATE_CASE(name, id, b3op, inc) case OpType::name:
    FOR_EACH_WASM_CONTROL_FLOW_OP(CREATE_CASE)
        return true;
#undef CREATE_CASE
    default:
        break;
    }
    return false;
}

inline bool isSimple(UnaryOpType op)
{
    switch (op) {
#define CREATE_CASE(name, id, b3op, inc) case UnaryOpType::name:
    FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE)
        return true;
#undef CREATE_CASE
    default:
        break;
    }
    return false;
}

inline bool isSimple(BinaryOpType op)
{
    switch (op) {
#define CREATE_CASE(name, id, b3op, inc) case BinaryOpType::name:
    FOR_EACH_WASM_SIMPLE_BINARY_OP(CREATE_CASE)
        return true;
#undef CREATE_CASE
    default:
        break;
    }
    return false;
}

inline uint32_t memoryLog2Alignment(OpType op)
{
    switch (op) {
    case I64Load32U: return 2;
    case I64Load32S: return 2;
    case I32Load16S: return 1;
    case I32Load16U: return 1;
    case I64Load: return 3;
    case F64Load: return 3;
    case I32Load8S: return 0;
    case I32Load8U: return 0;
    case I32Load: return 2;
    case F32Load: return 2;
    case I64Load8U: return 0;
    case I64Load8S: return 0;
    case I64Load16S: return 1;
    case I64Load16U: return 1;
    case I64Store16: return 1;
    case I64Store8: return 0;
    case I32Store: return 2;
    case I32Store16: return 1;
    case F32Store: return 2;
    case I64Store: return 3;
    case F64Store: return 3;
    case I32Store8: return 0;
    case I64Store32: return 2;
    default:
        break;
    }
    RELEASE_ASSERT_NOT_REACHED();
    return 0;
}

#define CREATE_CASE(name, id, b3type, inc) case name: return #name;
inline const char* makeString(OpType op)
{
    switch (op) {
    FOR_EACH_WASM_OP(CREATE_CASE)
    }
    RELEASE_ASSERT_NOT_REACHED();
    return nullptr;
}
#undef CREATE_CASE

} } // namespace JSC::Wasm

#endif // ENABLE(WEBASSEMBLY)

